package com.yycx.module.bus.provider.service.hy.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.ConvertUtils;
import com.yycx.module.bus.client.entity.*;
import com.yycx.module.bus.client.entity.hy.BusHyorderInovice;
import com.yycx.module.bus.client.entity.hy.BusHyorderInoviceDetails;
import com.yycx.module.bus.client.entity.hy.BusHyorderReturn;
import com.yycx.module.bus.provider.mapper.hy.BusHyorderInoviceDetailsMapper;
import com.yycx.module.bus.provider.service.BusDrugsService;
import com.yycx.module.bus.provider.service.hy.BusHyorderInoviceDetailsService;
import com.yycx.module.bus.provider.service.hy.BusHyorderReturnService;
import com.yycx.module.bus.provider.service.BusPaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 开票明细接口实现类
 *
 * @author flyme
 * @date 2023-09-17
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BusHyorderInoviceDetailsServiceImpl extends BaseServiceImpl<BusHyorderInoviceDetailsMapper, BusHyorderInoviceDetails> implements BusHyorderInoviceDetailsService {

    @Autowired
    @Lazy
    private BusHyorderReturnService hyorderReturnService;

    @Autowired
    @Lazy
    private BusPaymentService paymentService;

    @Autowired
    @Lazy
    private BusDrugsService drugsService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusHyorderInoviceDetails bhid, EntityMap extra) {
        return ResultBody.ok();
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusHyorderInoviceDetails> cq, BusHyorderInoviceDetails bhid, EntityMap requestMap) {
        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<BusHyorderInoviceDetails> cd) {
        Serializable invoiceDetailsId = cd.getIdValue();
        BusHyorderInoviceDetails orderInoviceDetails = getById(invoiceDetailsId);
        if (FlymeUtils.isNotEmpty(orderInoviceDetails)) {
            Integer settleType = orderInoviceDetails.getSettleType();
            Long orderDetailsReturnId = orderInoviceDetails.getOrderDetailsReturnId();
            hyorderReturnService.clearSettleApplyId(orderDetailsReturnId, settleType);
            BigDecimal settleApplyAmount = FlymeUtils.getBigDecimal(orderInoviceDetails.getSettleApplyAmount(), "0");
            Long paymentId = orderInoviceDetails.getSettleApplyId();
            BusPayment payment = paymentService.getById(paymentId);
            if (FlymeUtils.isNotEmpty(payment)) {
                BigDecimal amount = payment.getAmount();
                amount = amount.subtract(settleApplyAmount);
                payment.setAmount(amount);
                paymentService.updateById(payment);
            }
        }
        return super.beforeDelete(cd);
    }

    /**
     * 添加开票明细
     *
     * @param selectIds
     * @param payment
     * @param invoiceUnitId
     * @return
     */
    public Boolean addInoviceDetails(String selectIds, BusPayment payment, Long invoiceUnitId) {

        return true;
    }

    /**
     * 拆分金额
     *
     * @param invoiceDetailsId
     * @param amount
     * @return
     */
    @Override
    public BusHyorderInoviceDetails cfAmount(Long invoiceDetailsId, BigDecimal amount) {
        BusHyorderInoviceDetails orderInoviceDetails = getById(invoiceDetailsId);
        if (FlymeUtils.isNotEmpty(orderInoviceDetails)) {
            BigDecimal oldAmount = orderInoviceDetails.getSettleApplyAmount();
            BigDecimal surplusAmount = oldAmount.subtract(amount);
            ApiAssert.gezero("金额不足", surplusAmount);
            if (FlymeUtils.gtzero(surplusAmount)) {
                orderInoviceDetails.setSettleApplyAmount(surplusAmount);
                BusHyorderInoviceDetails newObj = new BusHyorderInoviceDetails();
                BeanUtil.copyProperties(orderInoviceDetails, newObj);
                newObj.setSettleApplyAmount(amount);
                newObj.setInvoiceDetailsId(IdWorker.getId());
                newObj.setParentId(invoiceDetailsId);
                save(newObj);
                updateById(orderInoviceDetails);
                return newObj;
            } else {
                updateById(orderInoviceDetails);
                return orderInoviceDetails;
            }
        }
        return null;
    }


    @Override
    public ResultBody revokeCfAmount(Long invoiceDetailsId) {
        BusHyorderInoviceDetails inoviceDetails = getById(invoiceDetailsId);
        if (FlymeUtils.isNotEmpty(inoviceDetails)) {
            BigDecimal oldAmount = inoviceDetails.getSettleApplyAmount();
            Long parentId = inoviceDetails.getParentId();
            if (FlymeUtils.isNotEmpty(parentId)) {
                BusHyorderInoviceDetails parent = getById(parentId);
                BigDecimal parentAmount = parent.getSettleApplyAmount().add(oldAmount);
                parent.setSettleApplyAmount(parentAmount);
                updateById(parent);
                removeById(invoiceDetailsId);
            }
        }
        return ResultBody.ok("撤销成功");
    }

    @Override
    public EntityMap totalSettleAmount(String settleIds) {
        CriteriaQuery<BusHyorderInoviceDetails> cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("sum(settleApplyAmount) settleAmount,deptId,companyId,count(DISTINCT saleManId) saleManIdCount,saleManId,deptId,settleApplyId,drugType");
        cq.in(true, "invoiceDetailsId", settleIds.split(","));
        return findOne(cq);
    }

    @Override
    public List<BusHyorderInoviceDetails> selectBySelectIds(String settleIds) {
        CriteriaQuery<BusHyorderInoviceDetails> cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("invoiceDetailsId", "settleApplyAmount", "saleManId", "deptId");
        cq.in(true, "invoiceDetailsId", settleIds.split(","));
        //未申请支付
        cq.isNull("payId");
        return list(cq);
    }

    @Override
    public List<BusHyorderInoviceDetails> selectByPayId(Long payId) {
        CriteriaQuery<BusHyorderInoviceDetails> cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("invoiceDetailsId", "settleApplyAmount", "saleManId", "deptId");
        cq.eq(true, "payId", payId);
        return list(cq);
    }


    @Override
    public EntityMap getInvoiceInfo(String selectIds) {
        CriteriaQuery<BusHyorderInoviceDetails> cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("sum(settleApplyAmount) settleAmount");
        cq.in(true, "invoiceDetailsId", selectIds.split(","));
        return findOne(cq);
    }

    @Override
    public Boolean updateSettleInvoiceId(BusHyorderInovice hyorderInovice, String[] payIds) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "invoiceUnitId", hyorderInovice.getInvoiceUnitId());
        cu.set(true, "settleFpId", hyorderInovice.getInoviceId());
        cu.in(true, "payId", payIds);
        return update(cu);
    }

    /**
     * 清空发票ID
     *
     * @param settleFpId
     * @return
     */
    @Override
    public Boolean clearSettleFpId(Serializable settleFpId) {
        if (FlymeUtils.allNotNull(settleFpId)) {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set(true, "settleFpId", null);
            cu.set(true, "invoiceUnitId", null);
            cu.eq(true, "settleFpId", settleFpId);
            update(cu);
        }
        return true;
    }

    @Override
    public Boolean updatePayInfo(Long paymentId, Date settleDate) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "settleDate", settleDate);
        cu.setSql("settleAmount=settleApplyAmount");
        cu.eq(true, "payId", paymentId);
        return update(cu);
    }

    @Override
    public Boolean updateSettleFpId(Long settleFpId, String selectIds) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "settleFpId", settleFpId);
        cu.in(true, "invoiceDetailsId", selectIds.split(","));
        return update(cu);
    }

    @Override
    public List<BusHyorderInoviceDetails> selectByIds(String settleIds) {
        CriteriaQuery cu = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cu.in(true, "invoiceDetailsId", settleIds.split(","));
        cu.orderByAsc("createTime");
        return list(cu);
    }

    @Override
    public BusHyorderInoviceDetails getByOrderDetailsReturnId(Long orderDetailsReturnId) {
        CriteriaQuery cu = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cu.eq(true, "orderDetailsReturnId", orderDetailsReturnId);
        return getOne(cu);
    }

    @Override
    public BusHyorderInoviceDetails getByOrderDetailsReturnId(String orderDetailsReturnId, Integer settleType) {
        CriteriaQuery cu = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cu.eq(true, "orderDetailsReturnId", orderDetailsReturnId);
        cu.eq(true, "settleType", settleType);
        return getOne(cu);
    }


    @Override
    public Boolean removeByOrderDetailsReturnId(Serializable settleApplyId) {
        CriteriaDelete cd = new CriteriaDelete();
        cd.eq(true, "settleApplyId", settleApplyId);
        return remove(cd);
    }



    @Override
    public List<EntityMap> selectByInvoiceId(Long invoiceId) {
        CriteriaQuery cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.addSelect("bhr.orderDetailsReturnId", "bhr.companyId", "bhr.drugJr", "bhr.drugNo", "bhr.orderDetailsId", "bhr.drugsName", "bhr.drugsSpec", "bhr.producersName", "format(bhr.saleNum,0) saleNum", "format(bhr.salePrice,2) salePrice", "format(bhr.costPrice,2) costPrice", "format(bhr.saleAmount,2) saleAmount", "format(bhr.costAmount,2) costAmount");
        cq.eq(true, "settleFpId", invoiceId);
        cq.createJoin(BusHyorderReturn.class).setMainField("orderDetailsId").setJoinField("orderDetailsId");
        cq.groupBy("bhr.drugNo", "bhr.salePrice");
        List<EntityMap> list = selectEntityMap(cq);
        if (FlymeUtils.isNotEmpty(list)) {
            for (EntityMap entityMap : list) {
                String drugNo = entityMap.get("drugNo");
                Long companyId = entityMap.getLong("companyId");
                BusDrugs drugs = drugsService.selectByDrugNo(drugNo, companyId);
                if (FlymeUtils.isNotEmpty(drugs)) {
                    BigDecimal retailPrice = drugs.getRetailPrice();
                    entityMap.put("retailPrice", retailPrice);
                }
            }
        }
        return list;
    }

    @Override
    public List<EntityMap> selectByInvoiceId2(Long invoiceId) {
        CriteriaQuery cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("ROUND(bhid.settleApplyAmount,2) settleAmount", "bhid.returnAmount", "bhid.orderDetailsReturnId");
        cq.addSelect(BusCustom.class, "customName");
        cq.eq(true, "settleFpId", invoiceId);
        cq.createJoin(BusCustom.class);
        cq.orderByAsc("bhid.returnDate");
        List<EntityMap> list = selectEntityMap(cq);
        for (EntityMap entityMap : list) {
            Long orderDetailsReturnId = entityMap.getLong("orderDetailsReturnId");
            CriteriaQuery cq2 = new CriteriaQuery(BusHyorderReturn.class);
            cq2.addSelect("orderDetailsReturnId", "orderDetailsId", "drugsName", "drugsSpec", "producersName", "format(saleNum,0) saleNum", "format(salePrice,2) salePrice", "format(costPrice,2) costPrice", "format(saleAmount,2) saleAmount", "format(costAmount,2) costAmount");
            cq2.eq(true, "orderDetailsReturnId", orderDetailsReturnId);
            EntityMap map = findOne(cq2);
            entityMap.putAll(map);
        }
        return list;
    }

    @Override
    public Boolean updateSettlePayId(Long paymentId, String selectIds) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "payId", paymentId);
        cu.in(true, "invoiceDetailsId", selectIds.split(","));
        return update(cu);
    }


    /**
     * 清空开票申请信息
     */
    @Override
    public Boolean clearPayId(Serializable payId, Integer settleType) {
        if (FlymeUtils.allNotNull(payId)) {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set(true, "payId", null);
            cu.set(true, "invoiceUnitId", null);
            cu.set(true, "payId", null);
            cu.set(true, "invoiceDate", null);
            cu.eq(true, "payId", payId);
            update(cu);
        }
        return true;
    }

    /**
     * 清空支付信息
     *
     * @param payId
     * @return
     */
    @Override
    public Boolean clearPayId(Serializable payId) {
        if (FlymeUtils.allNotNull(payId)) {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set(true, "payId", null);
            cu.eq(true, "payId", payId);
            update(cu);
        }
        return true;
    }

    /**
     * 清空支付信息
     *
     * @param payId
     * @return
     */
    @Override
    public Boolean clearPayIdByInvoiceDetailsId(Serializable invoiceDetailsId) {
        if (FlymeUtils.allNotNull(invoiceDetailsId)) {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set(true, "payId", null);
            cu.eq(true, "invoiceDetailsId", invoiceDetailsId);
            update(cu);
        }
        return true;
    }


    @Override
    public Integer countPayNum(String settleApplyId) {
        CriteriaQuery<BusHyorderInoviceDetails> cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("count(*)");
        cq.eq(true, "settleApplyId", settleApplyId);
        cq.isNull("payId");
        return getObj(cq, e -> Integer.parseInt(e.toString()));
    }

    @Override
    public String getDrugsNames(Long inoviceId) {
        List<String> drugNameList = new ArrayList<>();
        CriteriaQuery cq = new CriteriaQuery(BusHyorderInoviceDetails.class);
        cq.select("DISTINCT drugsName");
        cq.eq(true, "settleFpId", inoviceId);
        cq.createJoin(BusHyorderReturn.class).setMainField("orderDetailsId").setJoinField("orderDetailsId");
        List<EntityMap> list = selectEntityMap(cq);
        if (FlymeUtils.isNotEmpty(list)) {
            for (EntityMap entityMap : list) {
                String drugName = entityMap.get("drugsName");
                drugNameList.add(drugName);
            }
        }
        return ConvertUtils.listToString(drugNameList);
    }


    /**
     * 流程审批结束后添加结算数据
     *
     * @param businessKey
     */
    public void insertInvoiceDetails(String businessKey) {
        BusPayment payment = paymentService.getById(businessKey);
        ApiAssert.isNotEmpty("审批对象不存在", payment);
        Integer settleType = payment.getSettleType();
        List<BusHyorderReturn> busHyorderReturnList = hyorderReturnService.getByOrderDetailsId(payment.getPaymentId(), settleType);
        List<BusHyorderInoviceDetails> list = new ArrayList<>();
        for (BusHyorderReturn orderDetail : busHyorderReturnList) {
            Long settleApplyId = orderDetail.getSettleApplyId();
            Long settleApplyIdC = orderDetail.getSettleApplyIdC();
            Long settleApplyIdD = orderDetail.getSettleApplyIdD();
            Long settleApplyIdE = orderDetail.getSettleApplyIdE();
            BigDecimal saleAmount = FlymeUtils.getBigDecimal(orderDetail.getSettleAmount(), "0");
            BigDecimal saleAmountC = FlymeUtils.getBigDecimal(orderDetail.getSettleAmountC(), "0");
            BigDecimal saleAmountD = FlymeUtils.getBigDecimal(orderDetail.getSettleAmountD(), "0");
            BigDecimal saleAmountE = FlymeUtils.getBigDecimal(orderDetail.getSettleAmountE(), "0");
            Boolean tag = false;
            if (settleType.equals(1) && FlymeUtils.isNotEmpty(settleApplyId) && FlymeUtils.nezero(saleAmount)) {
                tag = true;
            }
            if (settleType.equals(2) && FlymeUtils.isNotEmpty(settleApplyIdD) && FlymeUtils.nezero(saleAmountD)) {
                tag = true;
            }
            if (settleType.equals(3) && FlymeUtils.isNotEmpty(settleApplyIdC) && FlymeUtils.nezero(saleAmountC)) {
                tag = true;
            }
            if (settleType.equals(4) && FlymeUtils.isNotEmpty(settleApplyIdE) && FlymeUtils.nezero(saleAmountE)) {
                tag = true;
            }
            if (tag) {
                Long orderDetailsReturnId = orderDetail.getOrderDetailsReturnId();
                BusHyorderInoviceDetails invoiceDetails = getByOrderDetailsReturnId(orderDetailsReturnId.toString(), settleType);
                if (FlymeUtils.isEmpty(invoiceDetails)) {
                    invoiceDetails = new BusHyorderInoviceDetails();
                    invoiceDetails.setOrderDetailsId(orderDetail.getOrderDetailsId());
                    invoiceDetails.setOrderDetailsReturnId(orderDetail.getOrderDetailsReturnId());
                    invoiceDetails.setOrderId(orderDetail.getOrderId());
                    invoiceDetails.setCompanyId(orderDetail.getCompanyId());
                }


                invoiceDetails.setSettleType(settleType);
                invoiceDetails.setCustomId(orderDetail.getCustomId());
                //结算申请ID
                invoiceDetails.setSettleApplyId(payment.getPaymentId());
                invoiceDetails.setDeptId(orderDetail.getDeptId());
                invoiceDetails.setDrugType(orderDetail.getDrugType());
                invoiceDetails.setReturnAmount(orderDetail.getReturnAmount());
                invoiceDetails.setReturnDate(orderDetail.getReturnDate());
                BigDecimal settleAmount = orderDetail.getSettleAmount();
                Long saleManId = orderDetail.getSaleManId();
                if (settleType.equals(2)) {
                    settleAmount = orderDetail.getSettleAmountD();
                    saleManId = orderDetail.getSaleManIdD();
                }
                if (settleType.equals(3)) {
                    settleAmount = orderDetail.getSettleAmountC();
                    saleManId = orderDetail.getSaleManIdC();
                }
                if (settleType.equals(4)) {
                    settleAmount = orderDetail.getSettleAmountE();
                    saleManId = orderDetail.getSaleManIdE();
                }
                invoiceDetails.setSettleApplyAmount(settleAmount);
                invoiceDetails.setSaleManId(saleManId);
                list.add(invoiceDetails);
            }
        }
        List<Long> ids = list.stream().map(BusHyorderInoviceDetails::getOrderDetailsReturnId).collect(Collectors.toList());
        if (FlymeUtils.isNotEmpty(ids)) {
            saveOrUpdateBatch(list);
        }

    }


}
